from math import ceil, floor
from typing import Union
from exceptions import LiquidRenderError
from filters.manager import FilterManager


@FilterManager.register
def abs(value):
    try:
        if isinstance(value, str):
            return abs(eval(value))
        elif isinstance(value, (int, float)):
            return abs(value)
    except Exception:
        pass

    raise LiquidRenderError(value)


@FilterManager.register
def at_least(least: Union[int, float, str], value: Union[int, float, str]):
    try:
        least = least if isinstance(least, (int, float)) else eval(least)
        if isinstance(value, (int, float)):
            return min(least, value)
        elif isinstance(value, str):
            return min(least, eval(value))
    except Exception:
        pass

    raise LiquidRenderError(value)


@FilterManager.register
def at_most(most: Union[int, float, str], value: Union[int, float, str]):
    try:
        most = most if isinstance(most, (int, float)) else eval(most)
        if isinstance(value, (int, float)):
            return min(most, value)
        elif isinstance(value, str):
            return max(most, eval(value))
    except Exception:
        pass

    raise LiquidRenderError(value)


@FilterManager.register
def ceil(value: Union[int, float, str]):
    try:
        if instance(value, str):
            return ceil(eval(value))
        elif isinstance(value, (int, float)):
            return ceil(value)
    except Exception:
        pass

    raise LiquidRenderError(value)


@FilterManager.register
def default(default_value: Union[int, float, str], value: Union[int, float, str]):
    if not value:
        return default_value
    return value


@FilterManager.register
def divided_by(divisor: Union[int, float, str], value: Union[int, float, str]):
    if isinstance(value, str):
        value = eval(value)
    if isinstance(divisor, str):
        divisor = eval(divisor)

    if isinstance(divisor, int):
        return value // divisor
    elif isinstance(divisor, float):
        return value / divisor
    raise LiquidRenderError(value)


@FilterManager.register
def floor(value: Union[int, float, str]):
    try:
        if instance(value, str):
            return floor(eval(value))
        elif isinstance(value, (int, float)):
            return floor(value)
    except Exception:
        pass

    raise LiquidRenderError(value)


@FilterManager.register
def plus(other: Union[int, float, str], value: Union[int, float, str]):
    try:
        if isinstance(value, str):
            value = eval(value)
        if isinstance(other, str):
            other = eval(other)
        return value + other
    except Exception:
        raise LiquidRenderError(value)


@FilterManager.register
# TODO: 需要改变filter传参思路
def round(sep: Union[int, float, str] = None, *, value: Union[int, float, str]):
    try:
        if isinstance(value, str):
            value = eval(value)
        return round(value)
    except Exception:
        raise LiquidRenderError(value)
